package com.fulihui.usercore.service;

import com.fulihui.usercore.api.CooperationInfoService;
import com.fulihui.usercore.common.util.Errors;
import com.fulihui.usercore.condition.CooperationInfoCondition;
import com.fulihui.usercore.core.repository.CooperationInfoRepository;
import com.fulihui.usercore.dto.CooperationInfoDTO;
import com.fulihui.usercore.request.merchant.CooperationInfoSaveRequest;
import org.apache.commons.collections.CollectionUtils;
import org.apache.dubbo.config.annotation.Service;
import org.near.servicesupport.error.CommonServiceErrorEnum;
import org.near.servicesupport.error.InvokeServiceException;
import org.near.servicesupport.request.TRequest;
import org.near.servicesupport.result.BaseResult;
import org.near.servicesupport.result.ResultBuilder;
import org.near.servicesupport.result.TMultiResult;
import org.near.servicesupport.result.TSingleResult;
import org.near.servicesupport.util.ServiceAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author Willard.Hu on 2016/9/22 0022.
 */
@Service(version = "1.0.0")
public class CooperationInfoServiceImpl implements CooperationInfoService {
    @Autowired
    private CooperationInfoRepository cooperationInfoRepository;

    /**
     * @see CooperationInfoService#save(CooperationInfoSaveRequest)
     */
    @Override
    @Transactional
    public TSingleResult<Integer> save(CooperationInfoSaveRequest request) {
        int id = request.getId();
        checkCooperationDate(request.getMid(), request.getId(), request.getStartDate(),
                request.getEndDate());
        if (request.getId() == -1) {
            id = cooperationInfoRepository.insert(request);
        } else {
            CooperationInfoDTO dto = cooperationInfoRepository.queryByPK(request.getId());
            ServiceAssert.notNull(dto, CommonServiceErrorEnum.REQUEST_PARAMETER_ERROR);
            // 起始时间和结束时间不能被更新
            ServiceAssert.isTrue(request.getStartDate() != -1,
                    CommonServiceErrorEnum.REQUEST_PARAMETER_ERROR);
            boolean b = cooperationInfoRepository.update(request);
            if (!b) {
                return ResultBuilder
                        .failTSingle(Errors.Merchant.COOPERATION_INFO_OPERATE_ERROR);
            }
        }
        return ResultBuilder.succTSingle(id);
    }

    /**
     * @see CooperationInfoService#delete(TRequest)
     */
    @Override
    public BaseResult delete(TRequest<Integer> request) {
        ServiceAssert.notNull(request.getCondition(),
                CommonServiceErrorEnum.REQUEST_PARAMETER_ERROR);
        boolean b = cooperationInfoRepository.delete(request.getCondition());
        return b ? ResultBuilder.succ(BaseResult.class) : ResultBuilder.fail(BaseResult.class,
                Errors.Merchant.COOPERATION_INFO_OPERATE_ERROR);
    }

    /**
     * @see CooperationInfoService#query(TRequest)
     */
    @Override
    public TMultiResult<CooperationInfoDTO> query(TRequest<CooperationInfoCondition> request) {
        List<CooperationInfoDTO> list = cooperationInfoRepository.query(request.getCondition());
        return ResultBuilder.succTMulti(list);
    }

    /**
     * 检查合作日期区间，遍历同商户下的合作方式判断区间是否合理，所有区间不能重叠
     *
     * @param mid       商户唯一标识
     * @param id        合作商主键
     * @param startDate 起始日期
     * @param endDate   结束日期
     */
    private void checkCooperationDate(final String mid, int id, final long startDate,
                                      final long endDate) {
        ServiceAssert.notBlank(mid, CommonServiceErrorEnum.REQUEST_PARAMETER_ERROR);

        // 只处理时间区间都有值的情况，否则被认为不做任何更新，所以无需判断
        if (startDate > -1) {
            // 当前合作时间起始值大于结束值为异常情况
            // 结束时间为-1表示无限长
            if (startDate >= endDate && endDate != -1) {
                throw new InvokeServiceException(Errors.Merchant.COOPERATION_TIME_ERROR);
            }
            CooperationInfoCondition condition = new CooperationInfoCondition();
            condition.setMid(mid);
            // 查询商户下的所有合作时间，按起始时间倒序
            List<CooperationInfoDTO> list = cooperationInfoRepository.query(condition);
            CooperationInfoDTO prev, next;

            // 获取当前数据的前后数据做时间校验
            if (id > -1) {
                // 更新时肯定存在数据，否则说明是无效的 mid
                if (CollectionUtils.isEmpty(list)) {
                    throw new InvokeServiceException(CommonServiceErrorEnum.REQUEST_PARAMETER_ERROR);
                }
                // 获得当前索引
                int currIdx = -1;
                for (int i = 0, size = list.size(); i < size; i++) {
                    if (list.get(i).getId() == id) {
                        currIdx = i;
                        break;
                    }
                }
                // 更新时id应该是存在的，否则说明是无效的 id
                if (currIdx == -1) {
                    throw new InvokeServiceException(CommonServiceErrorEnum.REQUEST_PARAMETER_ERROR);
                }
                // 因为list是倒序的，所以取实际相对数据的前后数据要倒着获取
                prev = currIdx < list.size() - 1 ? list.get(currIdx + 1) : null;
                next = currIdx > 0 ? list.get(currIdx - 1) : null;

            } else {
                // 新增数据只有上一条数据，没有后一条
                prev = CollectionUtils.isEmpty(list) ? null : list.get(0);
                next = null;
            }

            // 有上一条记录，校验其实时间是否有效（不能小于上一条的起始时间）
            if (prev != null) {
                // 当前合作时间起始值不能小于等于上一条合作时间起始值
                if (startDate <= prev.getStartDate()) {
                    throw new InvokeServiceException(Errors.Merchant.COOPERATION_TIME_ERROR);
                }
                // 当前合作时间起始值小于上一条合作时间结束值，更新上一条合作时间的结束值为当前合作时间起始值
                if (startDate < prev.getEndDate() || prev.getEndDate() == -1) {
                    CooperationInfoSaveRequest cooperationInfoSaveRequest = new CooperationInfoSaveRequest();
                    cooperationInfoSaveRequest.setId(prev.getId());
                    cooperationInfoSaveRequest.setEndDate(startDate - 1);
                    boolean b = cooperationInfoRepository.update(cooperationInfoSaveRequest);
                    if (!b) {
                        throw new InvokeServiceException(
                                Errors.Merchant.COOPERATION_INFO_OPERATE_ERROR);
                    }
                }
            }

            // 有后一条记录，校验时间是否有效（结束时间不能大于上一条的起始时间）
            if (next != null) {
                if (endDate > next.getStartDate() || endDate == -1) {
                    throw new InvokeServiceException(Errors.Merchant.COOPERATION_TIME_ERROR);
                }
            }
        }

    }
}
